#ifndef _SPLINEHELPER_H_
#define _SPLINEHELPER_H_

#include "Spline.h"

template<int Dim, int Order, SplineType t>
Vec<double,Dim> fnval(const Spline<Dim,Order,t>& sp, const double& x);

template<int Dim, int Order, SplineType t>
std::vector<Vec<double,Dim> > fnval(const Spline<Dim,Order,t>& sp, const std::vector<double>& x);

template<int Dim, int Order, SplineType t>
void fnplt(const Spline<Dim,Order,t>& sp, const std::string
           &_file, const int num = 200, const bool overwrite = 0,
           const bool isperiod = 0);

template<int Dim, int Order>
Spline<Dim,Order-1,ppForm> fnder(const Spline<Dim,Order,ppForm>& sp);

//BForm and cardinalB
template<int Dim, int Order, SplineType t>
Spline<Dim,Order-1,t> fnder(const Spline<Dim,Order,t>& sp);


template<int Dim, int Order, SplineType t>
Vec<double,Dim> fnval(const Spline<Dim,Order,t>& sp, const double& x){
     return sp(x);
}

template<int Dim, int Order, SplineType t>
std::vector<Vec<double,Dim> > fnval(const Spline<Dim,Order,t>& sp, const std::vector<double>& x){
  std::vector<Vec<double,Dim> > res;
  for(auto value:x)
    res.push_back(sp(value));
  return res;
}

template<int Dim, int Order, SplineType t>
void fnplt(const Spline<Dim,Order,t>& sp, const std::string
           &_file, const int num, const bool overwrite,
           const bool isperiod){
  switch(t){
  case ppForm:
    if (Dim == 1)
      fnplt<Order>(sp,_file,num,overwrite);
    else
      fnplt<Order>(sp,_file,num,isperiod,overwrite);
    break;
  case BForm: case cardinalB:
    fnplt<Order>(sp,_file,num,overwrite);  
  }
}

template<int Dim, int Order>
Spline<Dim,Order-1,ppForm> fnder(const Spline<Dim,Order,ppForm>& sp){
  Spline<Dim,Order-1,ppForm> res;
  res.setknots(sp.getknots());
  const std::vector<Polynomial<Order,Vec<double,Dim> > >& oldpolys =
    sp.getpolys();
  std::vector<Polynomial<Order-1,Vec<double,Dim> > > newpolys;
  for (auto p:oldpolys)
    newpolys.push_back(p.der());
  res.setpolys(newpolys);
  return res;
}

template<int Dim, int Order, SplineType t>
Spline<Dim,Order-1,t> fnder(const Spline<Dim,Order,t>& sp){
  Spline<Dim,Order-1,t> res;
  res.setcoes(sp.getcoes());
  const std::vector<Bspline<1,Order> >& oldbasis = sp.getbasis();
  std::vector<Bspline<1,Order-1> > newbasis;
  for (auto p:oldbasis)
    newbasis.push_back(p.der());
  res.setbasis(newbasis);
  return res;
}



#endif // _SPLINEHELPER_H_
